﻿// -----------------------------------------------------------------------
// <copyright file="Time.cs" company="The Usual Dosage">
// © 2013 by Matthew M. Martin
// </copyright>
// -----------------------------------------------------------------------

namespace Cadence.NET
{
    using System;

    /// <summary>
    /// Represents a single unit of time.
    /// </summary>
    public class Time
    {
        #region Properties

        /// <summary>
        /// Gets or sets the hour.
        /// </summary>
        /// <value>
        /// The hour.
        /// </value>
        private int? hour = (int?)null;
        public int? Hour
        {
            get
            {
                return hour;
            }
            set
            {
                if (value.HasValue && value != -1 && ((value <= 0) || (value > 24)))
                    throw new InvalidOperationException("Hour must be a value between 1 and 24.");
                else
                    hour = value;
            }
        }

        private int? minute = (int?)null;
        /// <summary>
        /// Gets or sets the minute.
        /// </summary>
        /// <value>
        /// The minute.
        /// </value>
        public int? Minute
        {
            get
            {
                return minute;
            }
            set
            {
                if (value.HasValue && value != -1 && (value < 0) || (value > 59))
                    throw new InvalidOperationException("Minute must be a value between 0 and 59.");
                else
                    minute = value;
            }
        }

        private int? second = (int?)null;
        /// <summary>
        /// Gets or sets the second.
        /// </summary>
        /// <value>
        /// The second.
        /// </value>
        public int? Second
        {
            get
            {
                return second;
            }
            set
            {
                if (value.HasValue && value != -1 && (value < 0) || (value > 59))
                    throw new InvalidOperationException("Second must be a value between 0 and 59.");
                else
                    second = value;
            }
        }

        /// <summary>
        /// Gets or sets the millisecond.
        /// </summary>
        /// <value>
        /// The millisecond.
        /// </value>
        public int? Millisecond { get; set; }

        #endregion Properties

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="Time"/> class.
        /// </summary>
        /// <param name="hour">The hour.</param>
        /// <param name="minute">The minute.</param>
        /// <param name="second">The second.</param>
        /// <param name="millisecond">The millisecond.</param>
        public Time(int hour = -1, int minute = -1, int second = -1, int millisecond = -1) 
        {
            if (hour == -1)
                Hour = (int?)null;
            else
                Hour = hour;

            if (minute == -1)
                Minute = (int?)null;
            else
                Minute = minute;

            if (second == -1)
                Second = (int?)null;
            else
                Second = second;

            if (millisecond == -1)
                Millisecond = (int?)null;
            else
                Millisecond = millisecond;
        }

        #endregion Constructor

        #region Methods

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            DateTime testDate = (DateTime)obj;
            DateTime now = DateTime.Now;
            DateTime compareDate = new DateTime(now.Year, now.Month, now.Day, testDate.Hour, testDate.Minute, testDate.Second);
            DateTime thisDate = new DateTime(now.Year, now.Month, now.Day, this.Hour.HasValue ? this.Hour.Value : testDate.Hour, 
                this.Minute.HasValue ? this.Minute.Value : testDate.Minute, this.Second.HasValue ? this.Second.Value : testDate.Second);
            return compareDate == thisDate;
        }

        /// <summary>
        /// Calculates the interval.
        /// </summary>
        /// <returns></returns>
        public int CalculateInterval()
        {
            if (this != null)
            {
                int hour = this.Hour.HasValue ? this.Hour.Value * 3600000 : 0;
                int minute = this.Minute.HasValue ? this.Minute.Value * 60000 : 0;
                int second = this.Second.HasValue ? this.Second.Value * 1000 : 0;
                int millisecond = this.Millisecond.HasValue ? this.Millisecond.Value : 0;
                return hour + minute + second + millisecond;
            }
            else
                return 0;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #endregion Methods
    }
}
